Return ignoring of native grab/ungrab events when we don't have a grab
authorAlexander Larsson <alexl@redhat.com>
Tue, 3 Feb 2009 19:15:19 +0000 (20:15 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:15:30 +0000 (10:15 +0200)
It turns out we really have to ignore grab/ungrab events or we'll
report double crossing events when we grab or ungrab.

However, we also can't ignore crossing events from grabs from other clients
as that leads to missed enter/leave events on e.g. alt-tab in metacity.

Fortunately we now track grabs very precisely, so we know with certainty
whether we have a grab at the time (serial) of the native crossing events,
and only if we do we ignore them.

gdk/gdkwindow.c

index 9b18240cd0163773287bc587429f52ac1781a233..dfa12141b7c05021441f9a5e6abbd5613b47ea10 100644 (file)
@@ -8647,6 +8647,32 @@ _gdk_windowing_got_event (GdkDisplay *display,
       return;
     }
 
+  if ((event->type == GDK_ENTER_NOTIFY ||
+       event->type == GDK_LEAVE_NOTIFY) &&
+      (event->crossing.mode == GDK_CROSSING_GRAB ||
+       event->crossing.mode == GDK_CROSSING_UNGRAB) &&
+      _gdk_display_has_pointer_grab (display, serial))
+    {
+      /* We synthesize all crossing events due to grabs outselves,
+       * so we ignore the native ones when we already have a grab.
+       * Otherwise we would send multiple events when this app grabs
+       * We want to handle grabs from other clients though. */
+
+      /* We ended up in this window after some (perhaps other clients)
+        grab, so update the toplevel_under_window state */
+      if (is_toplevel &&
+         event->type == GDK_ENTER_NOTIFY &&
+         event->crossing.mode == GDK_CROSSING_UNGRAB)
+       {
+         if (display->pointer_info.toplevel_under_pointer)
+           g_object_unref (display->pointer_info.toplevel_under_pointer);
+         display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
+       }
+      
+      unlink_event = TRUE;
+      goto out;
+    }
+  
   /* Track toplevel_under_pointer */
   if (is_toplevel)
     {
@@ -8707,6 +8733,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
        }
     }
 
+ out:
   if (unlink_event)
     {
       _gdk_event_queue_remove_link (display, event_link);